package com.github.niefy.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author : [86188]
 * @description : 创建共享线程池
 * @createTime : [2023/5/19 15:59]
 * @updateUser : [86188]
 * @updateTime : [2023/5/19 15:59]
 */
@Configuration
public class TaskExcutor {

    public static ThreadPoolTaskExecutor taskExecutor;
    public static ThreadPoolTaskScheduler schedulerExecutor;

    @Bean("taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //设置线程池参数信息
        taskExecutor.setCorePoolSize(10);
        taskExecutor.setMaxPoolSize(20);
        taskExecutor.setQueueCapacity(200);
        taskExecutor.setKeepAliveSeconds(60);
        taskExecutor.setThreadNamePrefix("taskExecutor--");
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.setAwaitTerminationSeconds(60);
        //修改拒绝策略为使用当前线程执行
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //初始化线程池
        taskExecutor.initialize();
        TaskExcutor.taskExecutor = taskExecutor;
        return taskExecutor;
    }

    // 用来存入线程执行情况, 方便于停止定时任务时使用
    public static ConcurrentHashMap<String, ScheduledFuture> cache= new ConcurrentHashMap<>();

    @Bean("schedulerExecutor")
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(10);                        // 线程池大小
        threadPoolTaskScheduler.setThreadNamePrefix("schedulerExecutor-");   // 线程名称
        threadPoolTaskScheduler.setAwaitTerminationSeconds(60);         // 等待时长
        threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);  // 调度器shutdown被调用时等待当前被调度的任务完成
        TaskExcutor.schedulerExecutor = threadPoolTaskScheduler;
        return threadPoolTaskScheduler;
    }

    /**
     * 将任务提交到系统线程池中执行
     * 1.如果线程数未达核心线程，创建核心线程
     * 2.已达核心线程数，添加到任务队列
     * 3.核心线程已满、队列已满，创建新空闲线程
     * 4.核心线程已满、队列已满、无法创建新空闲线程，执行拒绝策略
     * 本工具类拒绝策略使用内置ThreadPoolExecutor.CallerRunsPolicy，即让添加任务的主线程来执行任务，这样主线程被占用无法继续添加任务，相当于线程池全满后添加任务的线程会被阻塞
     * @param task
     * @return
     */
    public static Future<?> submit(Runnable task){
        return TaskExcutor.taskExecutor.submit(task);
    }

    /**
     * 将定时任务添加到系统线程池
     */
    public static ScheduledFuture<?> schedule(Runnable task,Instant scheduleTime){
        return TaskExcutor.schedulerExecutor.schedule(task,scheduleTime);
    }
}
